package com.itcast.demo.proxy;

import com.itcast.demo.proxy.service.Subject;
import com.itcast.demo.proxy.service.impl.SubjectImpl;
import sun.misc.ProxyGenerator;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;

/**
 * 测试类
 *
 * @author zheng.zhang
 */
public class DynamicProxyTest {
    public static void main(String[] args) {
        // 代理的真实对象
        Subject subject = new SubjectImpl();
        /*
         * InvocationHandlerImpl 实现了 InvocationHandler 接口，并能实现方法调用从代理类到委托类的分派转发
         * 其内部通常包含指向委托类实例的引用，用于真正执行分派转发过来的方法调用.
         * 即：要代理哪个真实对象，就将该对象传进去，最后是通过该真实对象来调用其方法
         */
        InvocationHandlerImpl handler = new InvocationHandlerImpl(subject);

        ClassLoader classLoader = subject.getClass().getClassLoader();
        Class<?>[] interfaces = subject.getClass().getInterfaces();
        // 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(classLoader, interfaces, handler);

        System.out.println("代理的对象类型为: " + proxyInstance.getClass().getName());

        String hello = proxyInstance.sayHello("涨涨");
        System.out.println(hello);

        System.out.println("<=====================================>");

        String goodBye = proxyInstance.sayGoodBye();
        System.out.println(goodBye);

        // 将代理生成的字节码文件保存到本地
        createProxyClassFile();
    }

    /**
     * 将代理类字节码保存到本地
     */
    private static void createProxyClassFile() {
        String proxyName = "ProxySubject";
        byte[] data = ProxyGenerator.generateProxyClass(proxyName, new Class[]{Subject.class});
        try (FileOutputStream out = new FileOutputStream(proxyName + ".class")) {
            System.out.println(new File("Hello").getAbsolutePath());
            out.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
